package pacs_server

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/uni-minds/bridge-pacs/dcm4chee"
	"gitee.com/uni-minds/bridge-pacs/global"
	"gitee.com/uni-minds/bridge-pacs/tools"
	"time"
)

// region Func Studies

func (pi *PacsServer) FindStudiesById(studiesId string) (info global.StudiesInfo, err error) {
	if info, err = pi.FindStudiesByIdLocal(studiesId); err == nil {
		return info, nil
	} else if _, err = pi.FindStudiesByIdWithHiddenLocal(studiesId); err == nil {
		return info, errors.New(fmt.Sprintf("studies hidden: %s", studiesId))
	}
	// 数据库无词条
	pi.Log("-   studies sync remote:", studiesId)

	connector := dcm4chee.NewConnector(pi.ServerHost, pi.ServerAETs)
	if studiesInfo, err := StudiesAnalysis(connector, studiesId); err != nil {
		return info, err
	} else if _, err = pi.ImportStudies(studiesInfo); err != nil {
		pi.Log("E", err.Error())
		return info, err
	} else {
		return pi.FindStudiesByIdLocal(studiesId)
	}
}
func (pi *PacsServer) FindStudiesByPatientName(pn string) (infos []global.StudiesInfo, err error) {
	h := pi.DbStudiesHandler()
	selector := fmt.Sprintf("%%%s%%", pn)
	data, err := h.Where("patient_name", "like", selector).Get()
	if err != nil {
		pi.Log("E find name:", err.Error())
		return nil, err
	} else {
		return pi.decodeStudiesInfos(data)
	}
}
func (pi *PacsServer) FindStudiesByPatientId(pid string) (infos []global.StudiesInfo, err error) {
	h := pi.DbStudiesHandler()
	data, err := h.Where("patient_id", pid).Get()
	if err != nil {
		pi.Log("E find pid:", err.Error())
		return nil, err
	} else {
		return pi.decodeStudiesInfos(data)
	}
}
func (pi *PacsServer) FindStudiesByStudiesDatetime(tStart, tEnd time.Time) (infos []global.StudiesInfo, err error) {
	data, err := pi.DbStudiesHandler().WhereBetween("studies_datetime", []interface{}{tools.TimeEncode(tStart), tools.TimeEncode(tEnd)}).Get()
	if err != nil {
		pi.Log("E find studies by Studies datetime:", err.Error())
	}
	return pi.decodeStudiesInfos(data)
}
func (pi *PacsServer) FindStudiesByUpdateDatetime(tStart, tEnd time.Time) (infos []global.StudiesInfo, err error) {
	data, err := pi.DbStudiesHandler().WhereBetween("update_datetime", []interface{}{tools.TimeEncode(tStart), tools.TimeEncode(tEnd)}).Get()
	if err != nil {
		pi.Log("E find studies by update datetime:", err.Error())
	}
	return pi.decodeStudiesInfos(data)
}
func (pi *PacsServer) FindStudiesByIdLocal(studiesId string) (info global.StudiesInfo, err error) {
	h := pi.DbStudiesHandler()
	data, err := h.Where("studies_id", studiesId).First()
	//pi.Log("SQL:", h.LastSql())
	if err != nil {
		pi.Log("E find sid 1:", err.Error())
		return info, err
	}

	if info, err = pi.decodeStudiesInfo(data); err != nil {
		return info, err
	} else if info.StudiesId == "" {
		return info, errors.New("not found")
	} else {
		return info, err
	}
}

func (pi *PacsServer) FindStudiesByIdWithHiddenLocal(studiesId string) (info global.StudiesInfo, err error) {
	if pi.ShowHidden {
		return pi.FindStudiesByIdLocal(studiesId)
	} else {
		pi.ShowHidden = true
		info, err := pi.FindStudiesByIdLocal(studiesId)
		pi.ShowHidden = false
		return info, err
	}
}

func (pi *PacsServer) StudiesUpdateTag(id string, key, value string) (err error) {
	return pi.dbUpdateStudies(id, map[string]interface{}{key: value})
}
func (pi *PacsServer) StudiesUpdateAll(id string, info global.StudiesInfo) (err error) {
	var data map[string]interface{}
	bs, _ := json.Marshal(info)
	if err = json.Unmarshal(bs, &data); err != nil {
		return err
	}

	return pi.dbUpdateStudies(id, data)
}
func (pi *PacsServer) StudiesUpdateLabel(id string, label global.LabelStudies) (err error) {
	var info global.StudiesInfo
	if info, err = pi.FindStudiesById(id); err != nil {
		return err
	}

	ok, err := pi.StudiesCheckPermissionAuthor(id, label.Uid)
	if err != nil {
		return err
	} else if !ok && !label.OpOverride {
		return errors.New("no permission, wrong user without override")
	}

	if label.OpRemove {
		info.LabelUidAuthor = 0
		info.LabelUidReview = 0
		info.LabelHisInfo = ""
		info.LabelProgress = 0
		info.LabelInfoAttend = ""
		info.LabelMemo = ""
	} else {
		info.LabelHisInfo = label.HisInfo
		info.LabelProgress = label.Progress
		info.LabelInfoAttend = label.InfoAttend
		info.LabelMemo = label.Memo
	}
	return pi.StudiesUpdateAll(id, info)
}
func (pi *PacsServer) StudiesUpdateLabelProgress(id string, progress int) (err error) {
	return pi.dbUpdateStudies(id, map[string]interface{}{"label_progress": progress})
}
func (pi *PacsServer) StudiesUpdateLabelHisInformation(id string, info string) (err error) {
	return pi.dbUpdateStudies(id, map[string]interface{}{"label_his_info": info})
}
func (pi *PacsServer) StudiesUpdateLabelMemo(id string, info string) (err error) {
	m := map[string]interface{}{"label_memo": info}
	return pi.dbUpdateStudies(id, m)
}
func (pi *PacsServer) StudiesUpdateLabelInfoAttend(id string, info string) (err error) {
	m := map[string]interface{}{"label_info_attend": info}
	return pi.dbUpdateStudies(id, m)
}
func (pi *PacsServer) StudiesUpdateLabelUidAuthor(id string, uid int) (err error) {
	m := map[string]interface{}{"label_uid_author": uid}
	return pi.dbUpdateStudies(id, m)
}
func (pi *PacsServer) StudiesUpdateLabelUidReview(id string, uid int) (err error) {
	m := map[string]interface{}{"label_uid_review": uid}
	return pi.dbUpdateStudies(id, m)
}

func (pi *PacsServer) StudiesInsertSeriesId(studiesId, seriesId string) (err error) {
	info, err := pi.FindStudiesById(studiesId)
	if err != nil {
		return err
	}

	result, _, err := tools.IdStrInsertIdStr(info.IncludeSeries, seriesId)
	if err != nil {
		return err
	}

	return pi.StudiesUpdateTag(studiesId, "include_series", result)
}
func (pi *PacsServer) StudiesRemoveSeriesId(studiesId, seriesId string) (err error) {
	info, err := pi.FindStudiesByIdLocal(studiesId)
	if err != nil {
		pi.Logf("E studies remove series: %s/%s\n", studiesId, seriesId)
		return nil
	}

	result, cnt, err := tools.IdStrRemoveIdStr(info.IncludeSeries, seriesId)
	if err != nil {
		return err

	} else if cnt < 1 {

		if err = pi.dbRemoveStudies(studiesId); err != nil {
			pi.Logf("E removing studies: %s\n", err.Error())
		}
		return nil

	} else {
		return pi.StudiesUpdateTag(studiesId, "include_series", result)
	}
}
func (pi *PacsServer) RemoveStudies(studiesId string, isRemoveChild bool) (err error) {
	info, err := pi.FindStudiesByIdLocal(studiesId)
	if err != nil {
		return err
	}

	if isRemoveChild {
		for _, seriesId := range tools.IdStrDecodeString(info.IncludeSeries) {
			if err = pi.RemoveSeries(studiesId, seriesId, isRemoveChild); err != nil {
				pi.Logf("E remove series %s: %s\n", seriesId, err.Error())
			}
		}
	}

	if _, err = pi.FindStudiesByIdLocal(studiesId); err == nil {
		pi.Log("Warning force remove studies")
		if err = pi.dbRemoveStudies(studiesId); err != nil {
			pi.Logf("E remove studies %s: %s\n", studiesId, err.Error())
		}
	}

	return nil
}

func (pi *PacsServer) StudiesSetTagDelete(id string, delete bool) (err error) {
	value := 0
	if delete {
		value = 1
	}

	return pi.dbUpdateStudies(id, map[string]interface{}{"db_delete": value, "db_hidden": 0})
}
func (pi *PacsServer) StudiesSetTagHidden(id string, hidden bool) (err error) {
	value := 0
	if hidden {
		value = 1
	}

	tmpHiddenFlag := pi.ShowHidden
	pi.ShowHidden = true
	err = pi.dbUpdateStudies(id, map[string]interface{}{"db_hidden": value})
	pi.ShowHidden = tmpHiddenFlag
	return err
}

func (pi *PacsServer) StudiesCheckPermissionAuthor(id string, uid int) (ok bool, err error) {
	info, err := pi.FindStudiesById(id)
	if err != nil {
		return false, err
	}

	if info.LabelUidAuthor == 0 || info.LabelUidAuthor == uid || info.LabelUidReview == uid {
		return true, nil
	} else {
		return false, errors.New("user has no premission")
	}
}
func (pi *PacsServer) StudiesCheckPermissionReview(id string, uid int) (ok bool, err error) {
	info, err := pi.FindStudiesById(id)
	if err != nil {
		return false, err
	}

	if info.LabelUidReview == 0 || info.LabelUidReview == uid {
		return true, nil
	} else {
		return false, errors.New("user has no premission")
	}
}

// endregion
